#ifndef TASKDISPATCHER_H_
#define TASKDISPATCHER_H_

//boost headers
#include <boost/thread.hpp>
#include <boost/ref.hpp>


//std headers
#include <string>
#include <vector>
#include <map>

//project headers
#include <SingletonHolder.h>
#include "ITask.h"



namespace Tasks{

	//! TaskDispatcher
	/*!
		Predstavuje triedu na spravu uloh ktore vie modul vykonavat.
		A na automaticku aktivaciu ulohy na zaklade zakodovaneho
		prikazu.
	*/

	template<typename T> class TaskDispatcher
	{
		public:
			//! TaskDispatcher (Konstruktor)
			/*!
				Sluzi na inicializaciu objektu a na inicializaciu
				zakladnej sady uloh
			*/
			TaskDispatcher(void)
			{}


			//! ~TaskDispatcher (Destruktor)
			/*!
				Uvolni vsetky zdroje
			*/
			~TaskDispatcher(void)
			{}

			//! RegisterTask
			/*!
				Funkcia sluzi na zaregistrovanie novej ulohy
				\param char commandCode kod ulohy
				\param ITask * theTask smernik na ulohu
				\return bool true ak registracia prebehla v poriadku, false inak
			*/
			bool Register(char commandCode, ITask<T> *theTask)
			{
                typedef typename RegisteredTasks::iterator RegisteredTasksIterator;
                //std::pair<RegisteredTasks::iterator,bool> _ret;
                std::pair<RegisteredTasksIterator,bool> _ret;

				_ret = myTasks.insert(std::pair<char,ITask<T>*>(commandCode,theTask));

				return _ret.second;
			}

			bool Execute(char commandCode,T data)
			{
				try
				{
				    typedef typename RegisteredTasks::const_pointer RegisteredTasksConstPtr;
					RegisteredTasksConstPtr _iter = myTasks.find(commandCode);
					if(_iter != myTasks.end())
					{
						_iter->second->Load(data);
						_iter->second();
						return true;
					}

					return false;
				}
				catch (...)
				{
					return false;
				}

			}

			bool ExecuteAsync(char commandCode,T data)
			{
				try
				{
				    typedef typename RegisteredTasks::const_iterator RegisteredTasksConstItr;
					RegisteredTasksConstItr _iter = myTasks.find(commandCode);
					if(_iter != myTasks.end())
					{
						_iter->second->Load(data);

						ITask<T> *myP = _iter->second;
						boost::thread task_inth(boost::ref(*myP));
						return true;
					}
					return false;
				}
				catch (...)
				{
					SingletonHolder::Instance().WriteEx("Faild to run a task with CommandCode:" +commandCode);
					return false;
				}
			}


		private:
			typedef std::map<char,ITask<T>*> RegisteredTasks;
			RegisteredTasks myTasks;

	};
}//end of Tasks namespace


#endif//TASKDISPATCHER_H_
